#include "Client.h"

#include "../util/definitions.h"

#include <iostream>
#include <unistd.h>
#include <fcntl.h>

Client::Client(){

	my_mtype = getpid();
	is_channel_open = false;
}

Client::~Client() {

}

int Client::getRegister(std::string name, DBRegister *reg) {

	int ret = result_error;

	if ( reg != NULL ) {

		try {

			reg->setName(name.c_str());

			ret = requestServer(request_get, reg, true);

		} catch ( MessageQueueException &e ) {
			ret = result_server_error;
			is_channel_open = false;
		}
	}

	return ret;
}

int Client::insertRegister(DBRegister *reg) {
	int ret = result_error;

	if ( reg != NULL ) {

		try {

			ret = requestServer(request_insert, reg);


		} catch ( MessageQueueException &e ) {
			ret = result_server_error;
			is_channel_open = false;
		}
	}

	return ret;
}


int Client::removeRegister(DBRegister *reg) {

	int ret = result_error;

	if ( reg != NULL ) {

		try {

			ret = requestServer(request_remove, reg);

		} catch ( MessageQueueException &e ) {
			ret = result_server_error;
			is_channel_open = false;
		}
	}

	return ret;
}

int Client::updateRegister(DBRegister *reg) {

	int ret = result_error;

	if ( reg != NULL ) {

		try {

			ret = requestServer(request_update, reg);

		} catch ( MessageQueueException &e ) {
			ret = result_server_error;
			is_channel_open = false;
		}
	}

	return ret;
}

int Client::requestServer(int request_id, DBRegister *reg, bool update_myreg) {

	int ret = result_error;

	if ( reg != NULL ) {

		/* abro el canal si está cerrado */
		openChannel();

		/* armo la request para enviar al servidor */

		Message request;
		request.mtype 		= MTYPE_SERVER;		/* mtype en el que escucha el servidor */
		request.dst_mtype	= this->my_mtype;	/* mtype en el que voy a esperar la respuesta */
		request.cmd			= request_id;		/* tipo de request */
		request.reg			= (*reg);			/* registro con el que se trabaja */

		std::clog<<"--Enviando request al servidor"<<std::endl;

		ret = channel.send(& request);	/* envio la solicitud al servidor */

		if ( ret == 0 ) {

			/* la request se envio exitosamente .. espero la respuesta del servidor */

			std::clog<<"--Esperando respuesta del servidor"<<std::endl;

			Message response;

			ret = channel.receive(this->my_mtype, &response);

			std::clog<<"--Respuesta recibida"<<std::endl;

			ret = response.cmd;		  	/* resultado de la operación */

			if ( ret == result_ok && update_myreg )
				(*reg) = response.reg;	/* si fue exitosa, copio el registro que me envio el servidor */
		}
	}

	return ret;
}

void Client::openChannel() {
	if (  !is_channel_open && isServerOnline()) {
		channel.open(MESSAGE_QUEUE_F, MESSAGE_QUEUE_L);
		is_channel_open = true;
	}
}

bool Client::isServerOnline() {
	int fd = open(MESSAGE_QUEUE_F,O_RDONLY, 0660);

	if (fd > 0)
		close(fd);
	return fd > 0;
}
